<template>
    <div class="file-upload">
        <div class="file-upload-container" @click.prevent="triggerUpload" v-bind="$attrs">
            <slot v-if="fileStatus == 'loading'" name="loading">
                <button class="btn btn-primary" disabled>正在上传...</button>
            </slot>
            <slot v-else-if="fileStatus == 'success'" name="success" :uploadedData = "uploadedData">
                <button class="btn btn-primary" disabled>上传成功</button>
            </slot>
            <slot v-else-if="fileStatus == 'error'" name="error">
                <button class="btn btn-primary" disabled>上传失败</button>
            </slot>
            <slot v-else name="default">
                <button class="btn btn-primary" disabled>点击上传</button>
            </slot>
           
        </div>
        <input 
            type="file"
            class="file-input d-none"
            ref="fileInput"
            @change="handleFilechange"
        >
    </div>
</template>
<script lang="ts" setup>
import { ref, defineProps,defineEmits} from 'vue';
import { PropType } from 'vue';
import httpInstance from '@/axios';
type UploadStatus = 'ready' | 'loading' | 'success' | 'error'
type CheckFunction = (file:File) => boolean
const props = defineProps({
    action:{
        type:String,
        required:true
    },
    beforerUpload:{
        type:Function as PropType<CheckFunction>
    }
})
//使用透传属性：禁止将父组件的属性直接绑定到子组件的根节点上
//再使用v-bind="$attrs"，将透传属性绑定到指定的dom节点上
inheritAttrs:false
const uploadedData = ref()
const emits = defineEmits(['file-uploaded','file-uploaded-error'])
//使用ref获取dom节点
const fileInput = ref<null | HTMLInputElement>(null)
const fileStatus = ref<UploadStatus>('ready')
//当点击上传的按钮时，相当于点击文件选择框
const triggerUpload = () =>{
    if(fileInput.value){
        fileInput.value.click()
    }
}
//选择文件时的处理事件
const handleFilechange = (e:Event) =>{
    const currentTarget = e.target as HTMLInputElement
    if(currentTarget.files){
        const files = Array.from(currentTarget.files)
        //如果文件的格式符合则上传，否则进行返回
        if(props.beforerUpload){
            const result = props.beforerUpload(files[0])
            if(!result){
                return 
            }
        }
        fileStatus.value = 'loading'
        const formData = new FormData()
        formData.append('file',files[0])
        httpInstance.post(props.action,formData,{
            headers:{
                'Content-Type':'multipart/form-data'
            }
        }).then(resp =>{
            //触发成功的自定义事件
            emits('file-uploaded',resp.data)
            fileStatus.value = 'success'
            uploadedData.value = resp.data
        }).catch((error) =>{
            //触发失败的自定义事件
            emits('file-uploaded-error',error)
            fileStatus.value = 'error'
        }).finally(()=>{
            if(fileInput.value){
                fileInput.value.value = ''
            }
        })
    }
}
</script>
<style>

</style>